package com.iwdnb.gkgz.application.collect;

import java.time.DayOfWeek;
import java.time.LocalDate;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

import com.iwdnb.gkgz.application.service.RealTimeStockService;
import com.iwdnb.gkgz.application.service.StockPoolService;
import com.iwdnb.gkgz.application.collect.bean.StockDataChangeEvent;
import com.iwdnb.gkgz.application.vo.RealtimeStockData;
import com.iwdnb.gkgz.common.model.dto.Stock;
import com.iwdnb.gkgz.application.vo.StockClosedException;
import com.iwdnb.gkgz.application.vo.StockConstants;
import com.iwdnb.gkgz.application.vo.StockStatus;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StopWatch;

/**
 * @author pengl
 * @date 2020/05/03
 **/
@Component
public class StockDataManager implements InitializingBean {
    public static final Logger logger = LoggerFactory.getLogger(StockDataManager.class);


    //市场交易状态检测执行器
    ScheduledExecutorService stockStatusCheckExecutor;

    //股票实时数据收集执行器
    ScheduledExecutorService stockDataCollectExecutor;


    @Autowired
    ApplicationContext applicationContext;

    @Autowired
    RealTimeStockService realTimeStockService;


    @Autowired
    StockPoolService stockPoolService;

//    @Autowired
//    MailService mailService;

    //@Autowired
    //RobotMsgService robotMsgService;

    //收集执行服务是否启动
    private boolean isCollectStarted;

    private StockStatus lastStockStatus;

    public void doCheckStockStatusTask(){
        logger.info("doCheckStockStatusTask");
        stockStatusCheckExecutor.scheduleWithFixedDelay(() -> {
            logger.info("task schedule,isCollectStarted:{}",isCollectStarted);

//            if(isCollectStarted) {
//                return;
//            }

            try {
                tryStartCollectStockRealtimeData();
            }catch (Exception e){
                logger.error("tryStartCollectStockRealtimeData occur exception:{}",e.getMessage());
                String msg = "启动实时抓取股票数据服务报错，" + e.getMessage();
                sendMailToSystemManager(StockConstants.STOCK_SUBJECT,msg);
            }

        }, 0, StockConstants.STATUS_CHECK_INTERVAL_MINUTES, TimeUnit.MINUTES);
    }


    /**
     * 启动实时获取股票数据
     */
    private void tryStartCollectStockRealtimeData() {
        logger.info("tryStartCollectStockRealtimeData");

        DayOfWeek dayOfWeek = LocalDate.now().getDayOfWeek();
        if(dayOfWeek == DayOfWeek.SATURDAY || dayOfWeek == DayOfWeek.SUNDAY){
            isCollectStarted = false;
            logger.info("start collect fail,not trade day");
            return;
        }

        StockStatus status = realTimeStockService.getStockStatus();
        if(status == null) {
            isCollectStarted = false;
            logger.info("start collect fail,stockStatus is null");
            return;
        }

        if(status != lastStockStatus && lastStockStatus != null){
            sendMailToSystemManager(StockConstants.STOCK_SUBJECT, "市场交易状态变更:" + status.getName());
        }

        lastStockStatus = status;

        if(status != StockStatus.TRADING) {
            isCollectStarted = false;
            logger.info("start collect fail,stock status is {}",status.getName());
            return;
        }

        if(isCollectStarted) return;
        isCollectStarted = true;

        stockDataCollectExecutor.scheduleWithFixedDelay(() -> {
            if(!isCollectStarted) {
                logger.info("schedule collect fail,stock has been closed");
                throw new StockClosedException("stock is closed");
            }

            fireCollectStockRealtimeData();

        }, 0, StockConstants.DATA_REFRESH_INTERVAL_SECONDS, TimeUnit.SECONDS);
    }

    private void fireCollectStockRealtimeData() {
        try {
            StopWatch stopWatch = new StopWatch("CollectStockRealtimeData");
            stopWatch.start("getStockList");
            List<Stock> stockList = stockPoolService.getStockList();
            stopWatch.stop();
            if(CollectionUtils.isEmpty(stockList)){
                logger.warn("stockPoolList is empty");
                return;
            }


            stopWatch.start("getStockDataList");
            Map<String, RealtimeStockData> stockDataMap = realTimeStockService.getStockDataList(stockList);
            stopWatch.stop();

//            logger.info("task run time/ms:{}",stopWatch.getTotalTimeMillis());

            if(stopWatch.getTotalTimeMillis() >= StockConstants.DATA_REFRESH_INTERVAL_SECONDS * 1000 / 2){
                //获取数据超过间隔一半，属于网络高延时情况
                logger.warn("getStockDataList,Network high latency");
            }

            if(CollectionUtils.isEmpty(stockDataMap)){
                logger.warn("stockDataMap is empty");
                return;
            }


            //send to message center
            //暂时使用spring内置应用事件机制
            applicationContext.publishEvent(new StockDataChangeEvent(stockDataMap));

        }catch (Exception e){
            logger.error("fireCollectStockRealtimeData error:{}",e.getMessage());
            String msg = "实时抓取股票数据报错，" + e.getMessage();
            sendMailToSystemManager(StockConstants.STOCK_SUBJECT,msg);
        }
    }


    private void sendMailToSystemManager(String subject,String text){
        //不发送邮件
//        MailVO mailVO = new MailVO();
//        mailVO.setText(text);
//        mailVO.setSubject(StringUtils.isEmpty(subject) ? "" : subject);
//
//        mailService.sendMailToManager(mailVO);

        //RobotMessage robotMessage = new RobotMessage();
        //robotMessage.setContent(text);
        //robotMsgService.sendMessage(robotMessage);
    }

    //是否在交易中
    public boolean isTrading() {
        return isCollectStarted;
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        String property = applicationContext.getEnvironment().getProperty("config.stock.realtimeDataService.isOpen");
        logger.info("realtimeDataService isOpen:{}", property);
        if(property == null || "true".equals(property)) {
            this.stockStatusCheckExecutor = Executors.newSingleThreadScheduledExecutor();
            this.stockDataCollectExecutor = Executors.newSingleThreadScheduledExecutor();

            doCheckStockStatusTask();
        }
    }
}
